package org.huis.system.service;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.huis.common.core.domain.R;
import org.huis.common.core.enums.ResultCode;
import org.huis.common.core.enums.UserIdentity;
import org.huis.common.security.exception.ServiceException;
import org.huis.common.security.service.TokenService;
import org.huis.system.domain.entity.SysUser;
import org.huis.system.domain.dto.SysUserSaveDTO;
import org.huis.system.mapper.SysUserMapper;
import org.huis.system.utils.BCryptUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author huis
 * @date 2024/8/4 19:22
 */
@Service
@RefreshScope // 注解的作用？？
public class SysUserServiceImpl implements ISysUserService{
    @Autowired
    private SysUserMapper sysUserMapper;
    @Value("${jwt.secret}")
    private String secret;
    @Autowired
    private TokenService tokenService;

    @Override
    public R<String> login(String userAccount, String password) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        SysUser sysUser = sysUserMapper.selectOne(queryWrapper
                .select(SysUser::getUserId, SysUser::getPassword, SysUser::getNickName)
                .eq(SysUser::getUserAccount, userAccount));
        if(sysUser == null){
            return R.fail(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        if(BCryptUtils.matchesPassword(password,sysUser.getPassword())){
            // 将用户的登录信息存入到redis中，userKey作为key的一部分，同时存入jwt用于查询redis
            return R.ok(ResultCode.SUCCESS.getMsg(),
                    tokenService.createToken(sysUser.getUserId(),secret, UserIdentity.ADMIN.getValue()));
            // bug:如果用户重复发送登录请求，就会不断地像redis中写入键值对
            // 方案一、使用前缀+userId作为key，重复向redis中添加键值对是就会对上一个进行覆盖
            //        缺点：JWT令牌根据盐值+userId生成，用户jwt的更换频率取决于盐值变化的频率，JWT存在被盗用的风险
            // 方案二、使用前缀+userId+UUID,用户重复登陆时，将上一个键值队进行删除

        }
        return  R.fail(ResultCode.FAILED_LOGIN);
    }

    @Override
    public int add(SysUserSaveDTO sysUserSaveDTO) {
        // 参数合法性判断
        // 前端判断，后端再判断一次
        checkParams();

        // 查询用户名是否重复
        List<SysUser> sysUserList= sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserAccount, sysUserSaveDTO.getUserAccount()));

        if(CollectionUtil.isNotEmpty(sysUserList)){
            throw new ServiceException(ResultCode.AILED_USER_EXISTS);
        }
        SysUser sysUser = new SysUser();
        sysUser.setUserAccount(sysUserSaveDTO.getUserAccount());
        sysUser.setPassword(BCryptUtils.encryptPassword(sysUserSaveDTO.getPassword()));
        return sysUserMapper.insert(sysUser);
    }

    private void checkParams() {
    }
}
